package mf.com.interceptor;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import mf.com.Utils.AuthContextUtil;
import mf.com.entity.system.SysUser;
import mf.com.vo.common.GlobalConstant;
import mf.com.vo.common.Result;
import mf.com.vo.common.ResultCodeEnum;
import org.jetbrains.annotations.NotNull;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.concurrent.TimeUnit;

/**
 * @Author: lmf
 * @Create: 2024/3/26 20:59
 * Description:  接口请求前拦截 对除白名单之外的接口进行token验证
 */
@Component // 交给spring管理
public class LoginAuthInterceptor implements HandlerInterceptor {
    @Resource
    private RedisTemplate<String,String> redisTemplate;

    /**
     * 对接口请求前进行拦截处理
     */
    @Override
    public boolean preHandle(HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler) throws Exception {
        // 获取请求方式
        final String method = request.getMethod();
        // 如果请求方式 options (预检请求) 直接放行
        if ("OPTIONS".equals(method)) {
            return true;
        }
        // 从请求头中获取token
        final String token = request.getHeader("token");
        // 获取redis中内容
        final String s = redisTemplate.opsForValue().get(GlobalConstant.TOKEN_PREFIX + token);
        // 如果token为空，或者redis中token过期 返回错误提示
        if (StrUtil.isEmpty(token) || StrUtil.isEmpty(s) ) {
//            responseNoLoginInfo(response);
            return true;
        }

        // 如果redis查询到用户信息那么放到ThreadLocal里
        final SysUser sysUser = JSON.parseObject(s, SysUser.class);
        AuthContextUtil.set(sysUser);
        // 把redis用户信息数据更新过期时间 设置为2小时后过期
        redisTemplate.expire(GlobalConstant.TOKEN_PREFIX + token, 2, TimeUnit.HOURS);
        return true;

    }

    /**
     * 响应无登录信息的请求
     *
     * @param response HTTP响应对象
     */
    private void responseNoLoginInfo(HttpServletResponse response) {
        // 创建一个失败的结果对象，并设置其错误码为LOGIN_AUTH
        final Result<Object> fail = Result.fail(null, ResultCodeEnum.LOGIN_AUTH);

        // 设置响应的字符编码为"utf-8"
        response.setCharacterEncoding("utf-8");

        // 设置响应的内容类型为"text/html"，并指定字符编码为"utf-8"
        response.setContentType("text/html;charset=utf-8");

        try (PrintWriter writer = response.getWriter()) {
            // 将失败的结果对象转换为JSON字符串，并写入到响应中
            writer.print(JSON.toJSONString(fail));
        } catch (IOException e) {
            // 如果在写入响应过程中发生异常，则抛出运行时异常
            throw new RuntimeException(e);
        }
    }

    /**
     * 对接口请求后进行处理
     */
    @Override
    public void afterCompletion(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler, @Nullable Exception ex) throws Exception {
        // 操作完后把ThreadLocal删除
//        AuthContextUtil.remove();
    }


}
